package org.malred.hospital.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.malred.hospital.common.R;

import org.malred.hospital.dto.MedicineHistoryOverDto;
import org.malred.hospital.dto.MedicineListItemDto;
import org.malred.hospital.dto.MedicineSave2ListDto;
import org.malred.hospital.dto.StudentMedicineListItemDto;
import org.malred.hospital.entity.*;
import org.malred.hospital.entity.TbMedicineList;
import org.malred.hospital.entity.TbMedicineList;
import org.malred.hospital.service.*;
import org.malred.hospital.service.MedicineListService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/medicine-list")
public class MedicineListController extends BaseController<TbMedicineList> {
    @Autowired
    DoctorService doctorService;
    @Autowired
    private MedicineListService service;
    @Autowired
    private MedicineService medicineService;
    @Autowired
    private MedicineHistoryService medicineHistoryService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private HistoryService historyService;

    @Override
    public R<List<TbMedicineList>> findAll() {
        return R.success(service.list());
    }

    @Override
    public R<TbMedicineList> findById(@PathVariable Long id) {
        return R.success(service.getById(id));
    }

    @GetMapping("/student/{sid}")
    public R<List<StudentMedicineListItemDto>> student(@PathVariable Long sid) {
        LambdaQueryWrapper<TbMedicineHistory> mhqw = new LambdaQueryWrapper<>();
        mhqw.eq(TbMedicineHistory::getStudentId, sid);
        // 多个药单记录
        List<TbMedicineHistory> mhList = medicineHistoryService.list(mhqw);

        if (mhList == null) {
            return R.success(null);
        }

        List<StudentMedicineListItemDto> collect = new ArrayList<>();
        for (TbMedicineHistory mh : mhList) {
            if (mh.getPrice() != null && mh.getPrice() != 0 && mh.getStatus() != 1L) {
                StudentMedicineListItemDto dto = new StudentMedicineListItemDto();
                dto.setMedicineHistoryId(mh.getId());
                dto.setTotalPrice(mh.getPrice());
                dto.setDoctorName(doctorService.getById(mh.getDoctorId()).getName());
                collect.add(dto);
            }
        }
//        List<StudentMedicineListItemDto> collect = mhList.stream().map(mh -> {
//            StudentMedicineListItemDto dto = new StudentMedicineListItemDto();
//            dto.setMedicineHistoryId(mh.getId());
//            dto.setTotalPrice(mh.getPrice());
//            dto.setDoctorName(doctorService.getById(mh.getDoctorId()).getName());
//            return dto;
//        }).collect(Collectors.toList());

        return R.success(collect);
    }

    /**
     * @param id 订单id
     * @return
     */
    @GetMapping("/dto/find/{id}")
    public R<List<MedicineListItemDto>> findDtoByOId(@PathVariable Long id) {
        // 通过orderid获取history(看病记录)
        LambdaQueryWrapper<TbHistory> hqw = new LambdaQueryWrapper<>();
        hqw.eq(TbHistory::getOrderId, id);
        TbHistory h = historyService.getOne(hqw);

        // 通过看病记录获取开药记录
        LambdaQueryWrapper<TbMedicineList> qw = new LambdaQueryWrapper<>();
        qw.eq(TbMedicineList::getMedicineHistoryId, h.getMedicineHistoryId());
        List<TbMedicineList> list = service.list(qw);

        List<MedicineListItemDto> collect = list.stream().map(l -> {
            MedicineListItemDto dto = new MedicineListItemDto();

            dto.setId(l.getId());
            dto.setMedicineHistoryId(l.getMedicineHistoryId());
            dto.setMedicine(
                    medicineService.getById(l.getMedicineId())
            );
            dto.setNumber(l.getNumber());
            dto.setPrice(
                    medicineService.getById(l.getMedicineId()).getPrice() * l.getNumber()
            );

            return dto;
        }).collect(Collectors.toList());

        return R.success(collect);
    }

    /**
     * @param id 药单id
     * @return
     */
    @GetMapping("/dto/find/mh/{id}")
    public R<List<MedicineListItemDto>> findDtoByMHId(@PathVariable Long id) {
        // 通过看病记录获取开药记录
        LambdaQueryWrapper<TbMedicineList> qw = new LambdaQueryWrapper<>();
        qw.eq(TbMedicineList::getMedicineHistoryId, id);
        List<TbMedicineList> list = service.list(qw);

        List<MedicineListItemDto> collect = list.stream().map(l -> {
            MedicineListItemDto dto = new MedicineListItemDto();

            dto.setId(l.getId());
            dto.setMedicineHistoryId(l.getMedicineHistoryId());
            dto.setMedicine(
                    medicineService.getById(l.getMedicineId())
            );
            dto.setNumber(l.getNumber());
            dto.setPrice(
                    medicineService.getById(l.getMedicineId()).getPrice() * l.getNumber()
            );

            return dto;
        }).collect(Collectors.toList());

        return R.success(collect);
    }

    @Override
    public R<TbMedicineList> insert(@RequestBody TbMedicineList dto) {
        if (service.save(dto)) {
            return R.success(dto);
        } else {
            return R.error("添加 [MedicineList] 失败");
        }
    }

    @PostMapping("/dto/save")
    public R<TbMedicineList> save2list(@RequestBody MedicineSave2ListDto dto) {
        log.info("MedicineSave2ListDto: {}", dto);
        // 根据订单id找到medicine history(在叫号时已经创建)
        LambdaQueryWrapper<TbHistory> hqw = new LambdaQueryWrapper<>();
        hqw.eq(TbHistory::getOrderId, dto.getOid());
        TbHistory h = historyService.getOne(hqw);

        if (h == null) {
            return R.error("该 [TbHistory] 不存在!");
        }
        TbMedicineHistory mh = medicineHistoryService.getById(h.getMedicineHistoryId());
        // 创建medicine list记录
        TbMedicineList ml = new TbMedicineList();
        ml.setMedicineHistoryId(mh.getId());
        ml.setNumber(dto.getNumber());
        ml.setMedicineId(dto.getMid());

        if (service.save(ml)) {
            return R.success(ml);
        }
        return R.error("添加 [TbMedicineList] 失败!");
    }

    @PutMapping("/dto/save")
    public R<TbMedicineList> uptItemNum(@RequestBody MedicineSave2ListDto dto) {
        log.info("MedicineSave2ListDto: {}", dto);
        TbMedicineList ml = service.getById(dto.getMid());
        ml.setNumber(dto.getNumber());
        if (service.saveOrUpdate(ml)) {
            return R.success(ml);
        }
        return R.error("添加 [TbMedicineList] 失败!");
    }

    @Transactional
    @PutMapping("/dto/over")
    public R<String> over(@RequestBody MedicineHistoryOverDto dto) {
        // 修改订单状态为已开单
        TbOrder o = orderService.getById(dto.getOrderId());
        if (o == null) {
            return R.error("[TbOrder] 该记录不存在!");
        }
        if (o.getStatus() == 2L) {
            return R.error("[TbOrder] 该记录已开单!");
        }
        o.setStatus(2L);
        if (!orderService.saveOrUpdate(o)) {
            return R.error("[TbOrder] 修改状态失败!");
        }

        TbHistory h = historyService.getById(o.getHistoryId());

        LambdaQueryWrapper<TbMedicineHistory> mhqw = new LambdaQueryWrapper<>();
        mhqw.eq(TbMedicineHistory::getHistoryId, h.getId());
        TbMedicineHistory mh = medicineHistoryService.getOne(mhqw);
        mh.setPrice(dto.getPrice());

        // 扣库存 -> 拿药时扣
        if (medicineHistoryService.saveOrUpdate(mh)) {
            return R.success("[TbMedicineHistory] 开单成功!");
        }
        return R.error("修改 [TbMedicineHistory] 失败!");
    }

    @Transactional
    @PutMapping("/pay/{id}")
    public R<String> pay(@PathVariable Long id) {
        // 根据mhid获取药单
//        TbMedicineHistory mh = medicineHistoryService.getById(id);
        // 获取所有药单项
        LambdaQueryWrapper<TbMedicineList> mlqw = new LambdaQueryWrapper<>();
        mlqw.eq(TbMedicineList::getMedicineHistoryId, id);
        List<TbMedicineList> list = service.list();

        for (TbMedicineList ml : list) {
            // 减库存
            TbMedicine m = medicineService.getById(ml.getMedicineId());
            m.setNumber(
                    m.getNumber() - ml.getNumber()
            );
            medicineService.saveOrUpdate(m);
        }

        TbMedicineHistory mh = medicineHistoryService.getById(id);
        // 已支付(拿)
        mh.setStatus(1L);
        medicineHistoryService.saveOrUpdate(mh);
        return R.success("支付成功!");
    }

    @Override
    public R<TbMedicineList> update(@RequestBody TbMedicineList dto) {
        if (service.save(dto)) {
            return R.success(dto);
        } else {
            return R.error("修改 [Medicine] 失败");
        }
    }

    @Override
    public R<TbMedicineList> delete(Long id) {
        if (service.removeById(id)) {
            return R.success(null);
        } else {
            return R.error("删除 [MedicineList] 失败");
        }
    }
}
